home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / PaintUndo.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  6KB  |  258 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <X11/IntrinsicP.h>
  16. #include "xpaint.h"
  17. #include "misc.h"
  18. #include "PaintP.h"
  19.  
  20. #define    GET_PW(w)    ((PaintWidget)(((PaintWidget)w)->paint.paint == None ? w : ((PaintWidget)w)->paint.paint))
  21.  
  22. void UndoSwap(Widget w)
  23. {
  24.     PaintWidget    pw = GET_PW(w);
  25.  
  26.     /*
  27.     ** No undo buffers
  28.     */
  29.     if (pw->paint.head == NULL)
  30.         return;
  31.     /*
  32.     **  Walked off the end of the undo buffers.
  33.     */
  34.     if (pw->paint.undo == NULL) {
  35.         for (pw->paint.undo = pw->paint.head; 
  36.              pw->paint.undo != NULL && !pw->paint.undo->valid; 
  37.              pw->paint.undo = pw->paint.undo->prev);
  38.     } else {
  39.         pw->paint.undo = pw->paint.undo->prev;
  40.     }
  41.  
  42.     PwUpdate(w, NULL, True);
  43. }
  44.  
  45. /*
  46. **
  47. **  Consider the undo system...
  48. **
  49. **   UndoBuffer 
  50. **
  51. **        0    1    2   3
  52. **
  53. **        ^    ^-- pw->paint.undo
  54. **        + pw->paint.top (base reference)
  55. **
  56. */
  57.  
  58. Pixmap PwUndoStart(Widget w, XRectangle *rect)
  59. {
  60.     PaintWidget        pw = GET_PW(w);
  61.     UndoStack        *cur, *nxt, *start;
  62.  
  63.     pw->paint.dirty = True;
  64.  
  65.     /*
  66.     **  If there are no undo buffers
  67.     */
  68.     if (pw->paint.head == NULL)
  69.         return pw->paint.base;
  70.  
  71.     /*
  72.     **  If we are in the middle, and need to start writing.
  73.     **    it means that we've been doing some undo, and thus
  74.     **    the next stuff in line is invalid.
  75.     */
  76.     cur = pw->paint.undo;
  77.     if (cur != pw->paint.head) {
  78.         if (cur == NULL) 
  79.             cur = pw->paint.tail;
  80.         for (; cur != NULL; cur = cur->next)
  81.             cur->valid = False;
  82.         if (pw->paint.undo == NULL) {
  83.             nxt = pw->paint.tail;
  84.         } else {
  85.             nxt = pw->paint.undo->next;
  86.         }
  87.         start = NULL;
  88.     } else if (cur->valid) {
  89.         /*
  90.         **  If the current is valid, then everthing behind it must be as well
  91.         **    therfor tail must be valid.
  92.         */
  93.         nxt = pw->paint.tail;
  94.         XCopyArea(XtDisplay(pw), nxt->pixmap, pw->paint.base,
  95.                 pw->paint.gc,
  96.                 nxt->box.x, nxt->box.y,
  97.                 nxt->box.width, nxt->box.height,
  98.                 nxt->box.x, nxt->box.y);
  99.  
  100.         /*
  101.         **  Unlink the tail, and move it to the front.
  102.         */
  103.         if (pw->paint.head != pw->paint.tail) {
  104.             if (nxt->next != NULL)
  105.                 nxt->next->prev = NULL;
  106.             pw->paint.tail = nxt->next;
  107.  
  108.             pw->paint.head->next = nxt;
  109.             nxt->next = NULL;
  110.             nxt->prev = pw->paint.head;
  111.             pw->paint.head = nxt;
  112.             start = pw->paint.tail;
  113.         } else {
  114.             start = nxt;
  115.         }
  116.     }
  117.  
  118.     if (start == NULL) {
  119.         /*
  120.         **  Nothing valid, copy the whole thing
  121.         */
  122.         XCopyArea(XtDisplay(pw), pw->paint.base, nxt->pixmap,
  123.                 pw->paint.gc,
  124.                 0, 0,
  125.                 pw->paint.drawWidth, pw->paint.drawHeight,
  126.                 0, 0);
  127.     } else {
  128.         for (cur = start; cur != pw->paint.head; cur = cur->next) {
  129.             XCopyArea(XtDisplay(pw), cur->pixmap, nxt->pixmap,
  130.                     pw->paint.gc,
  131.                     cur->box.x, cur->box.y,
  132.                     cur->box.width, cur->box.height,
  133.                     cur->box.x, cur->box.y);
  134.         }
  135.     }
  136.  
  137.     if (rect == NULL) {
  138.         nxt->box.x      = 0;
  139.         nxt->box.y      = 0;
  140.         nxt->box.width  = 0;
  141.         nxt->box.height = 0;
  142.     } else {
  143.         nxt->box = *rect;
  144.     }
  145.     nxt->valid      = True;
  146.  
  147.     pw->paint.undo = nxt;
  148.  
  149.     return nxt->pixmap;
  150. }
  151.  
  152.  
  153. void UndoStart(Widget w, OpInfo *info)
  154. {
  155.     if (info->surface != opPixmap)
  156.         return;
  157.  
  158.     info->drawable = PwUndoStart(w, NULL);
  159. }
  160.  
  161.  
  162. void    UndoStartPoint(Widget w, OpInfo *info, int x, int y)
  163. {
  164.     PaintWidget    pw = GET_PW(w);
  165.  
  166.     if (info->surface != opPixmap)
  167.         return;
  168.  
  169.     UndoStart(w, info);
  170.  
  171.     if (pw->paint.undo == NULL)
  172.         return;
  173.  
  174.     pw->paint.undo->box.x      = x - pw->paint.lineWidth;
  175.     pw->paint.undo->box.y      = y - pw->paint.lineWidth;
  176.     pw->paint.undo->box.width  = 1 + pw->paint.lineWidth * 2;
  177.     pw->paint.undo->box.height = 1 + pw->paint.lineWidth * 2;
  178. }
  179.  
  180. void UndoGrow(Widget w, int x, int y)
  181. {
  182.     PaintWidget    pw = GET_PW(w);
  183.     XRectangle    *rect;
  184.     int        dx, dy;
  185.  
  186.     if (pw->paint.undo == NULL)
  187.         return;
  188.  
  189.     rect = &pw->paint.undo->box;
  190.  
  191.     rect->x     += pw->paint.lineWidth;
  192.     rect->y     += pw->paint.lineWidth;
  193.     rect->width -= pw->paint.lineWidth * 2;
  194.     rect->height-= pw->paint.lineWidth * 2;
  195.  
  196.     dx = x - rect->x;
  197.     dy = y - rect->y;
  198.  
  199.     if (dx > 0) {
  200.         rect->width = MAX(rect->width, dx);
  201.     } else {
  202.         rect->width = (int)rect->width - dx + 1;
  203.         rect->x     = x;
  204.     }
  205.  
  206.     if (dy > 0) {
  207.         rect->height = MAX(rect->height, dy) + 1;
  208.     } else {
  209.         rect->height = (int)rect->height - dy + 1;
  210.         rect->y      = y;
  211.     }
  212.  
  213.     rect->x     -= pw->paint.lineWidth;
  214.     rect->y     -= pw->paint.lineWidth;
  215.     rect->width += pw->paint.lineWidth * 2;
  216.     rect->height+= pw->paint.lineWidth * 2;
  217. }
  218.  
  219. void PwUndoSetRectangle(Widget w, XRectangle *rect)
  220. {
  221.     PaintWidget    pw = GET_PW(w);
  222.  
  223.     if (pw->paint.undo == NULL)
  224.         return;
  225.  
  226.     pw->paint.undo->box = *rect;
  227. }
  228. void PwUndoAddRectangle(Widget w, XRectangle *rect)
  229. {
  230.     PaintWidget    pw = GET_PW(w);
  231.  
  232.     if (pw->paint.undo == NULL)
  233.         return;
  234.  
  235.     pw->paint.undo->box = *RectUnion(rect, &pw->paint.undo->box);
  236. }
  237.  
  238. void UndoSetRectangle(Widget w, XRectangle *rect)
  239. {
  240.     PaintWidget    pw = GET_PW(w);
  241.  
  242.     if (pw->paint.undo == NULL)
  243.         return;
  244.  
  245.     PwUndoSetRectangle(w, rect);
  246.  
  247.     pw->paint.undo->box.x     -= pw->paint.lineWidth;
  248.     pw->paint.undo->box.y     -= pw->paint.lineWidth;
  249.     pw->paint.undo->box.width += pw->paint.lineWidth * 2 + 1;
  250.     pw->paint.undo->box.height+= pw->paint.lineWidth * 2 + 1;
  251. }
  252.  
  253. void    UndoStartRectangle(Widget w, OpInfo *info, XRectangle *rect)
  254. {
  255.     UndoStart(w, info);
  256.     UndoSetRectangle(w, rect);
  257. }
  258.